#-------------------------------------------------------------------------------
# Name:        Game
# Purpose:
#
# Author:      Theo
#
# Created:     10/02/2012
# Copyright:   (c) Monxcleyr Productions 2012
# Licence:     GPL v3
#-------------------------------------------------------------------------------
#!/usr/bin/env python

import pygame, sys, cPickle, zlib, os, logging
import time as RTime
import config, key, sound, debug, options, common, world, menu, pause, stars, event, minigame
from ..gui import label
from ..tools import videotools
from pygame.locals import *
from . import __version__ #Import engine version


class Game:
  def __init__(self):

    # Class containing common engine variables
    logging.info('Engine Version %s' % __version__)
    self.common = common.Common()
    self.SW = self.common.reswidths[self.common.settings.res_setting] # Load up the defined resolution
    self.SH = int(self.SW / self.common.scale)
    self.size = (self.SW, self.SH)
    self.day = 0
    # The various surfaces the game will use
    self.menuS = pygame.Surface(self.common.initsize)
    self.menuS.set_colorkey((255,0,255))
    self.optionS = pygame.Surface(self.common.initsize)
    self.optionS.set_colorkey((255,0,255))
    self.gameS = pygame.Surface(self.common.initsize)
    self.gameS.set_colorkey((255,0,255))
    self.mapS = pygame.Surface(self.common.initsize)
    self.titleS = pygame.Surface(self.common.initsize)
    # Everything is draw onto preS before drawn to the screen
    self.preS = pygame.Surface((self.SW, self.SH))
    # Debug Screen so it can be drawn on top
    self.debugS = pygame.Surface(self.common.initsize, SRCALPHA)
    self.screen = pygame.display.set_mode((self.SW, self.SH), SRCALPHA|DOUBLEBUF)
    if self.common.settings.fullscreen == True:
      self.screen = pygame.display.set_mode(self.size, SRCALPHA|DOUBLEBUF|FULLSCREEN)
    pygame.display.set_caption('#HJ Game Engine Initializing...')
    self.poll = 0
    self.quit = 0
    # Boolean that holds if the size of the display screen has changed
    self.scalechanged = True
    # THis holds if the game is running in either debug mode, set by Main
    self.debugstates = (False, False)
    self.count = 0
    self.mapfollow = False
    # the speed of the physics simulation per step
    self.physicsstep = 90

    # Modes:
    # 0 = Main Menu
    # 1 = Game
    # 2 = New Game
    # 3 = Load Game
    # 4 = Options Menu
    # 5 = Pause Screen
    # 6 = Developer Console
    # 7 = Updater
    # 8 = Return to previous mode
    # 9 = LOLMINIGAME 1
    self.mode = 0
    self.prevmode = 0
    # List of named modes, for debug screen
    self.modes = ['Main Menu', 'Game', 'New Game', 'Load Game', 'Options Menu', 'Pause', 'Console', 'Updater', 'Previous', 'Minigame 1']

    # Create debug class
    self.debug = debug.Debug(False, self.preS, (5,5), (5,5), 4, __version__)

    # MINIGAME CLASS
    self.minigame = minigame.MiniGame(self.common, self.debug)

    # STARFIELD INIT
 # STARFIELD INIT
    self.starfield = stars.starfield()
    # (255,210,210) redish
    # (210,210,255) blueish
    # (255,255,210) yellowish
    star_sample = [(255,220,220,1),(255,255,255,2),(220,220,255,1),(255,255,220,1),\
      (255,220,220,2),(255,255,255,2),(255,255,255,3),(255,255,255,3),(255,255,255,2), \
      (255,255,255,1),(255,255,255,1),(255,255,255,1),(255,255,255,1),(255,255,255,1), \
      (255,210,210,2),(255,255,255,2),(255,255,255,3),(255,255,255,3),(255,255,255,2), \
      (255,255,255,1),(255,255,255,1),(255,255,255,2),(255,255,255,2),(255,255,255,2) ]
    self.starfield.add_layer(100, .5, "down", star_sample, self.common.initsize)
    self.starfield.add_layer(100, 1, "down", star_sample, self.common.initsize)
    self.starfield.add_layer(100, 1.25, "down", star_sample, self.common.initsize)
    self.starfield.add_layer(100, 1.5, "down", star_sample, self.common.initsize)
    self.eventType = ['radiation','breach','leak','hal 9000']
    self.eventfactory = event.eventFactory()
    self.prevTime = 0

    #Time
    
  def newGame(self):
    """ Creates a WHOLE NEW GAME! :O """

    # Create new instance of world class
    self.world = world.World(self.gameS)
    # initiate renderer
##    self.renderer = renderer.Renderer()
##    self.world.loadMap('space', self.screen)
####    self.world.initPymunk(self.screen)
##    self.renderer.load(self.world.currentmap, self.common.initsize)
    logging.info('New game created')


  def postInit(self):
    """ This is a work around method for loading sounds and such after using pygame.movie
    to play the splash screens. """

    self.common.settings.activate()
    self.sound = sound.effect('resources/config/sounds.ini', self.debug)
    self.music = sound.music('resources/config/sounds.ini', self.debug)
    self.menu = menu.Menu(self.menuS, 'menu.ini', self.common, self.sound, self.music, self.debug)
    self.options = options.Options(self.optionS, 'options.ini', self.common, self.sound, self.music, self.debug, self.size)
    # Pause Screen class
    self.pause = pause.Pause('pause.ini', self.common, self.sound, self.music, self.debug)

  def setMode(self, mode):
    """ Used to change the game's mode.
    Same as using game.mode = x """
    if self.mode != 8:
      if self.prevmode != mode and mode != self.mode:
        self.prevmode = self.mode
    self.mode = mode

  def usePrevMode(self):
    self.mode = self.prevmode
##    self.setMode(self.prevmode)
##    self.setMode(self.prevmode)

  def checkQuit(self):
    if self.quit == 1:
      return True
    else:
      return False

  def updatePreS(self, surface):

    # Draws the game to the main screen
    if surface.get_size() != self.screen.get_size():
      pygame.transform.smoothscale(surface, self.size, self.preS)
    else:
      self.preS.blit(surface, (0,0))

  def saveWorld(self, savename, load=True):
    """ PERMADEATH OR BUST, DO NOT USE THIS EVER """
    self.world.savename = savename
    tempsprites = self.world.imagehandler.sprites
    self.world.imagehandler.reset()
    self.world.removePymunk(self.screen)
    filename = 'Saves'
    f = open(os.path.join(filename, self.world.savename + '.hjsav'), 'wb')
    object1 = zlib.compress(cPickle.dumps(self.world, cPickle.HIGHEST_PROTOCOL),9)
    cPickle.dump(object1,f,cPickle.HIGHEST_PROTOCOL)
    f.close()
    self.world.imagehandler.sprites = tempsprites

    logging.info('Game %s saved', savename)
    if load == True:
      self.loadSave(savename)
##    self.world.loadPhysics(self.screen)
##    self.world.initPymunk(self.screen)

  def loadSave(self, savename):
    """ LOAD A SAVE LOLOL """
    filename = 'Saves'
    try:
      f = open(os.path.join(filename, savename + '.hjsav'),'rb')
      obj = cPickle.load(f)
      self.world = cPickle.loads(zlib.decompress(obj))
      f.close()
    except IOError as e:
      logging.critical('Failed to load save %s' % savename)

    # This makes the world reload the map, instead of using the one in memory, in case map
    # files were updated
    self.world.loadMap(self.world.currentmapname, self.screen)
    # Let the render load up the correct map
##    self.world.initPymunk(self.screen)
    self.renderer = renderer.Renderer()
    self.renderer.load(self.world.currentmap, self.common.initsize)
    self.world.createCollisionBodies(self.screen)
    # Reset camera pos to previous position
    self.renderer.moveCamera(self.world.camerapos)
    logging.info('Game %s loaded', savename)


  def changeMap(self, mapname, savename):
    """ Change map being used by the world and renderer"""
    self.saveWorld(savename, load=False)
    self.world.removePymunk(self.screen)
    self.world.loadMap(mapname, self.screen)
    self.world.camerapos = (0,0)
##    self.world.initPymunk(self.screen)
    self.renderer.load(self.world.currentmap, self.common.initsize)
    self.world.createCollisionBodies(self.screen)
    logging.info('Changed map to %s', mapname)

  #startTime = time event is activated
  #ednTime = time event is due
  def randomEvent(self, imagehandler, rectsize, active,startTime, endTime):
    self.randCoord = [(234,123),(123,253),(123,456)]
    rint = random.randint(1,3)
    if rint == 1:
      self.world.stations.addLeakEntity(randCord[random.randint(0,2)], 'leak.png', imagehandler, rectsize, 'leak', True)
      self.world.stations.addLeakEntity(randCord[random.randint(0,2)], 'leak.png', imagehandler, rectsize, 'leak', True)
      self.world.stations.addLeakEntity(randCord[random.randint(0,2)], 'leak.png', imagehandler, rectsize, 'leak', True)
      self.eventfactory.add_event('leak',endTime,"inactive",startTime)
    elif rint == 2:
      self.world.stations.addBreachEntity(randCord[random.randint(0,2)]), 'breach.png', imagehandler, rectsize, 'breach', True)
      self.world.stations.addBreachEntity((randCord[random.randint(0,2)], 'breach.png', imagehandler, rectsize, 'breach', True)
      self.world.stations.addBreachEntity(randCord[random.randint(0,2)], 'breach.png', imagehandler, rectsize, 'breach', True)
      self.eventfactory.add_event('breach',endTime,"inactive",startTime)
    elif rint == 3:
      self.world.stations.addAIPanelEntity((500,300), 'aipanel.png', imagehandler, rectsize, 'ai panel', True)
      self.eventfactory.add_event('hal 9000',endTime,"inactive",startTime)
    
#-------------------------------------------------------------------------------
#--------------------------------- Game Loop -----------------------------------
#-------------------------------------------------------------------------------

  def runGame(self, time, keyPressed):
    #Configure time
    self.common.time = time
    self.limit = 20
    elpTime = (int(round(self.world.runningtime/1000)) % self.limit) + 1
    timeLeft =  self.limit - elpTime
    self.gameS.fill((0,0,0))
    self.eventfactory.process_events(elpTime, self.world.stations)
    
    
    if self.eventfactory.is_failure() == True:
      #TEXT: YOU LOSE GOOD DAY SIR
    
    if elpTime == 1:
      if self.prevTime != elpTime:
        self.day = self.day + 1
        if self.day == 1:
          
          if elpTime == 15:
            #TEXT: Go to the life support and do life support stuff or whatever
          
          if elpTime == 30:
            #TEXT: Get some food, you dummy
          
          if elpTime == 45:
            #TEXT: Navigate somewhere over there or something
          
          if elpTime == 60:
            #TEXT: Oh no distress call
          
          if elpTime == 120:
            #TEXT: Wake up, son.
          
          self.random_event(  self.world.imagehandler, (40,40), True,1,15)
        elif self.day == 2:
          self.random_event(  self.world.imagehandler, (40,40), True,5,20)
          self.random_event(  self.world.imagehandler, (40,40), True,10,25)
        elif self.day == 3:
          self.random_event(  self.world.imagehandler, (40,40), True,15,30)
          self.random_event(  self.world.imagehandler, (40,40), True,10,15)
          self.random_event(  self.world.imagehandler, (40,40), True,15,20)
          if elpTime == self.limit:
            #THE END CATWOMAN BEGINS
          
    #if self.day == 1:
     # self.eventfactory.add_event(self.eventType[2],15,"inactive",5)

    # if self.day == 1:
    # elif self.day == 2:
    # elif self.day == 3:
    # else:
      
    # Calculate time of day
    # hours is length of day, dayinminutes is irl length of a day
    hours = 24.0
    dayinminutes = 2
    self.world.runningtime += time
    
    # Controls music queue
##    if self.music.getCurrentLoop() != self.world.currentmap.properties['music']:
##      self.music.loadQueue(self.world.currentmap.properties['music'])
##      self.music.playQueue()
##    if pygame.mixer.music.get_busy() == 0:
##      self.music.playQueue()
#-------------------------------------------------------------------------------
    key = pygame.key.get_pressed()
    # Bring up puase screen
    #if self.pause.gamecount > 10:
    if keyPressed['ESC'] == True:
      self.setMode(5)
#-------------------------------------------------------------------------------
    # Move test player
    tempx,tempy = 0,0
    impulse = (0,0)
    if key[self.common.key.bind['up']]:
      self.world.player.move((0,-2))
    if key[self.common.key.bind['down']]:
      self.world.player.move((0,2))
    if key[self.common.key.bind['left']]:
      self.world.player.move((-2,0))
    if key[self.common.key.bind['right']]:
      self.world.player.move((2,0))
    # Temporary function key stuff
    if key[pygame.K_F1]:
      self.mode = 9
##    if key[pygame.K_F2]:
##      self.loadSave('1')
##    if key[pygame.K_F6]:
##      if self.mapfollow:
##        self.mapfollow = False
##      else:
##        self.mapfollow = True
##    if key[pygame.K_F10]:
##      self.bullettime = True
    #self.world.updateCollisions()
    # DRAW STARFIELD
    self.starfield.draw(self.gameS)
    # DRAW SHIP
    self.gameS.blit(self.world.imagehandler.getSprite('ship.png'), self.world.shippos)
    self.world.stations.draw(self.gameS)
    self.world.player.checkInRange(self.world.stations)
    # Draw Player
    self.world.player.draw(self.gameS)
    font = pygame.font.Font(None,30)
    timeLabel = font.render(str(timeLeft), 1, (255,0,0))
    self.gameS.blit(timeLabel, (200,0))
    self.prevTime = elpTime
    for station in self.world.stations.stationList:
      if station.working == True:
        barWidth = 500
        portion = (station.work_required / 100.00)*float(barWidth)
        print (station.work_required / 100.00)
        outlineRect = pygame.Rect((300,0,barWidth,25))
        barRect = pygame.Rect((300,0,int(portion),25))
        pygame.draw.rect(self.gameS, (0,0,255),barRect)
        pygame.draw.rect(self.gameS, (255,0,0), outlineRect,2)
        actionLabel = font.render(str(station.type), 1, (0,0,0))
        
    #End of time

    
##    for tile in self.world.tilelist:
##      pygame.draw.rect(self.gameS, (255,0,0), tile.rect)



